import React from 'react';
import './index.less';
import { TreeData } from '../typings';
import TreeNode from './tree-node'
//整个树的组件属性对象
interface Props {
    data: TreeData
}
// 整个组件属性的初始状态
interface State {
        data: TreeData
    }
// 属性不确定[key] 但都是string类型而且在TreeData中
interface KeyToNodeMap {
    [key: string]: TreeData
}

class Tree extends React.Component<Props, State> {
    //数据初始值
    data: TreeData;
    keyToNodeMap: KeyToNodeMap;
    constructor(props: Props) {
        super(props);
        this.data = props.data;
        this.state={ data: this.props.data };//把属性传递给状态
        this.buildKeyMap();//迭代渲染key
    }
    //根据每个数据的key属性渲染
    buildKeyMap = () => {
        let data = this.data;
        this.keyToNodeMap = {}; //key节点的key值就是节点本身
        this.keyToNodeMap[data.key] = data;//根节点
        if (data.children && data.children.length > 0) {//遍历
            this.walk(data.children, data); //data.children儿子们 他爹data
        }
    }
    walk = (children: TreeData[], parent: TreeData): void => {   //void没有返回值
        children.map((item: TreeData) => {
            item.parent = parent; //在节点上增加一个parent属性，指定自己的父亲  作用：取消选中孙子，儿子父亲也会取消
            this.keyToNodeMap[item.key] = item; //每个儿子放进来
            if (item.children && item.children.length > 0) {  //有儿子且儿子数量大于零
                this.walk(item.children, item);
            }
        });
    }
    // 关闭打开树形
    onCollapse = (key: string) => {
        let data = this.keyToNodeMap[key];
        if (data) {
            data.collapsed = !data.collapsed;
            data.children = data.children || [];
            this.setState({ data: this.state.data });
        }
    }
    // 全选和取消功能
    onCheck = (key: string) => {
        let data: TreeData = this.keyToNodeMap[key];
        if (data) {
            data.checked = !data.checked;
            if (data.checked) {
                this.checkChildren(data.children, true);
                this.checkParentCheckAll(data.parent);
            } else {
                this.checkChildren(data.children, false);
                this.checkParent(data.parent, false);
            }
            this.setState({ data: this.state.data });
        }
    }
    checkParentCheckAll = (parent: TreeData) => {
        while (parent) {
            parent.checked = parent.children.every(item => item.checked);
            parent = parent.parent;
        }
    }
    checkParent = (parent: TreeData, checked: boolean) => {
        while (parent) {
            parent.checked = checked;
            parent = parent.parent;
        }
    }
    checkChildren = (children: Array<TreeData> = [], checked: boolean) => {
        children.forEach((item: TreeData) => {
            item.checked = checked;
            this.checkChildren(item.children, checked);
        });
    }
    render() {
        return(
            <div className='tree'>
                <div className='tree-nodes'>
                    <TreeNode data={this.props.data} onCollapse={this.onCollapse}
                    onCheck={this.onCheck}/>
                </div>
            </div>
        )
    }
}
export default Tree;